set more off
set matsize 1000

use cashier.dta, clear

capture program drop postreg
program postreg, eclass
	boottest `1', cluster(cashierid) nograph seed(12345)
	mat pboot = r(p) 
	mat ci = r(CI)
	estadd scalar lo = ci[1,1]
	estadd scalar hi = ci[1,2]
	
	forvalue i = 2(1)1000{
		if "``i''" == "" {
			continue, break
		}
		boottest ``i'', cluster(cashierid) nograph seed(12345)
		mat pboot = [pboot , r(p)]
	
	}
	
	mat colname pboot = `*' // _cons
	ereturn mat p = pboot
	
	unique cashierid if e(sample)
	estadd scalar cashier = r(unique), replace

end


** Table 1. Summary statistics**
eststo clear

estpost ttest scantime itempm itempm_tln, by(trad)
mat A = (e(mu_1)\ e(mu_2) \ e(b) \ e(se) \ e(p))'

preserve
gen customer = 1
collapse (sum) customer scantime paytime (mean) trad (max) timeonshift ///
	, by(store cashierid scan shiftno) 
gen worktime = scantime + paytime
gen cumtran = customer
label var worktime "Counter work time"
label var timeonshift "Time on shift"
label var cumtran "Cumulative transactions"
estpost ttest worktime timeonshift cumtran, by(trad)
mat A = A \ (e(mu_1)\ e(mu_2) \ e(b) \ e(se) \ e(p))'
mat colname A = "Scan-only checkout" "Conventional checkout" "Difference" "Standard error" "p-value"
restore

estpost ttest counter_close_prop paycash  ///
	basketsize basketval itemvalue  wed ///
	, by(trad)  
mat A = A \ (e(mu_1)\ e(mu_2) \ e(b) \ e(se) \ e(p))'

local rowname : rownames A

sum paytime
mat A = A \ (. \ r(mean) \ J(3,1,.))'

estpost ttest cashierid, by(trad)
mat A = A \ (e(N_1) \ e(N_2) \ J(3,1,.))'
unique cashierid
mat A = A \ (r(unique) \ J(4,1,.))'
unique store
mat A = A \ (r(unique) \ J(4,1,.))'
mat rowname A = `rowname' "payment time" "Observations" "Cashiers" "Store"
estout m(A, fmt(3 3 3 3 3)) using "Table1.xls", label replace    

  
** Figure 2. Scanning speed **
twoway (kdensity itempm_t if scan == 1 , lwidth(medthick)) ///
	(kdensity itempm_t if scan == 0 , lpatt(dash) lwidth(medthick)) , ///
	legend( label(1 "Scan-only") label(2 "Conventional") ) ///
	ytitle("Density") xtitle("Items per minute")
graph export "Figure2.png" , replace as(png) 


** Table 2. Cashier productivity **	
eststo clear

reg itempm_tln scan worktime_tln , cluster(cashierid) 
postreg scan worktime_tln 
eststo m1
  
reg itempm_tln scan worktime_tln  store_1 store_2 store_3, cluster(cashierid) 
postreg scan worktime_tln  store_1 store_2 store_3
eststo m2
  
areg itempm_tln scan worktime_tln, absorb(cashierid) cluster(cashierid) 
postreg scan worktime_tln 
eststo m3
    
areg itempm_tln scan worktime_tln i.date i.hour, absorb(cashierid) cluster(cashierid) 
postreg scan worktime_tln 
eststo m4

areg itempm_tln scan worktime_tln i.day##i.hour, absorb(cashierid) cluster(cashierid) 
postreg scan worktime_tln 
eststo m5

esttab m1 m2 m3 m4 m5 using "Table2.rtf", ///
	cells(b(star fmt(3)) p(par)) star(* 0.10 ** 0.05 *** 0.01)	nocons style(fixed) star ///
	stats(cashier N r2 lo hi, layout(@ @ @ `""[@, @]""') fmt(0 0 3)) label ///
	replace indicate("Date f.e. = *.date" "Hour f.e. = *.hour" ///
	"Day x Hour f.e. = *.day") mtitle("(a) Scan-only" "(b) Store f.e." "(c)Cashier f.e." ///
	"(d) Cashier, date & hour f.e." "(e) Cashier & day*hour f.e.") collabels(none) ///
	title("Table 2. Cashier Productivity")
	

** Table 3. Cashier Productivity: Alternative Explanations **
eststo clear
  
areg itempm_tln scan worktime_tln basketval_tln i.day##i.hour, absorb(cashierid) cluster(cashierid) 
postreg scan worktime_tln basketval_tln
eststo m1
  
areg itempm_tln scan worktime_tln basketval_tln i.day##i.hour subcat_q*, absorb(cashierid) cluster(cashierid) 
postreg scan worktime_tln basketval_tln
eststo m2

areg itempm_tln scan worktime_tln basketval_tln paycash i.day##i.hour subcat_q*, absorb(cashierid) cluster(cashierid) 
postreg scan worktime_tln basketval_tln paycash
eststo m3
  
areg itempm_tln scan worktime_tln basketval_tln paycash scan_wed i.day##i.hour subcat_q*, absorb(cashierid) cluster(cashierid) 
postreg scan worktime_tln basketval_tln paycash scan_wed
eststo m4

areg itempm_tln scan worktime_tln timeonshift_tln i.day##i.hour, absorb(cashierid) cluster(cashierid) 
postreg scan worktime_tln timeonshift_tln
eststo m5
  
areg itempm_tln scan worktime_tln counter_close_prop i.day##i.hour, absorb(cashierid) cluster(cashierid) 
postreg scan worktime_tln counter_close_prop
eststo m6

esttab m1 m2 m3 m4 m5 m6 using "Table3.rtf", ///
	cells(b(star fmt(3)) p(par)) star(* 0.10 ** 0.05 *** 0.01)	nocons style(fixed) ///
	stats(cashier N r2 lo hi, layout(@ @ @ `""[@, @]""') fmt(0 0 3)) label ///
	replace indicate("Product sub-cat f.e. = subcat_q*" ///
	"Day x Hour f.e. = *.day *.hour") ///
	mtitle("(a) Purchase char" "(b) Prod subcat" "(c) Payment mode" ///
	"(d) Wednesday" "(e) Fatigue" "(f) Packing help") collabels(none) ///
	title("Table 3. Cashier Productivity: Alternative Explanations")

** Table 4. Mechanism: Effort cost & task switching**

eststo clear

areg paytime_tln itempm_tln worktime_tln paycash  basketval_tln i.day##i.hour, absorb(cashierid) cluster(cashierid)
postreg itempm_tln worktime_tln paycash  basketval_tln
eststo m1

ivreg2 paytime_tln (itempm_tln = veg_ln ) worktime_tln paycash  basketval_tln i.day##i.hour i.cashierid, cluster(cashierid) ffirst
est store iv
areg itempm_tln veg_ln  worktime_tln paycash  basketval_tln i.day##i.hour if e(sample), absorb(cashierid) cluster(cashierid)
postreg veg_ln  worktime_tln paycash  basketval_tln
eststo m2

est restore iv  
postreg itempm_tln worktime_tln paycash  basketval_tln
eststo m3 

areg itempm_tln scan worktime_tln basketsize_tln basketsize_ave_tln_dm i.day##i.hour, absorb(cashierid) cluster(cashierid)
postreg scan worktime_tln basketsize_tln basketsize_ave_tln_dm
eststo m4
 
areg itempm_tln scan worktime_tln basketsize_tln basketsize_ave_tln_dm scan_basketsize_ave_tln_dm ///
	i.day##i.hour, absorb(cashierid) cluster(cashierid)
postreg scan worktime_tln basketsize_tln basketsize_ave_tln_dm scan_basketsize_ave_tln_dm
eststo m5

esttab m1 m2 m3 m4 m5 using "Table4.rtf", ///
	cells(b(star fmt(3)) p(par)) star(* 0.10 ** 0.05 *** 0.01)	nocons style(fixed) ///
	stats(cashier N r2 rkf lo hi, layout(@ @ @ @ `""[@, @]""') fmt(0 0 3)) label ///
	replace indicate("Cashier f.e. = *.cashierid" ///
	"Day x Hour f.e. = *.day *.hour") ///
	mtitle("(a) Effort-OLS" "(b) Effort-First stage" "(c) Effort-IV" "(d) Task switch" "(e) Task switch") ///
	collabels(none) order(itempm_tln $cntrvar) ///
	title("Table 4. Mechanism: Effort") 
	
	
** Figure 3: Cashier Productivity **
reg itempm_tln i.scan##i.cashierid i.day##i.hour, cluster(cashierid) nocon
mat A = e(b)
mat A = A[1,4..40]' , A[1,80..116]'
preserve
clear
svmat A
rename (A1 A2) (base prod_gain)
label var base "Conventional: Scanning speed"
label var prod_gain "Effect of scan-only"
twoway (scatter prod_gain base) (lfit prod_gain base , lwidth(medthick)) , ///
  legend(off) xlabel(-1(0.5)1) xtitle("Conventional checkout: Scanning speed") ///
  ytitle("Effect of scan-only") 
graph export "Figure3.png", replace   
restore
	

** Table B4: Cashier Productivity: Individual **
global outopt plain coljust(lc) var starloc(1) starlevels(10 5 1) ///
	 landscape stats(b p) bdec(3) tdec(3)
	
mat B = e(b)
mat B = B[1,3..40]'

preserve
collapse (mean) itempm_tln, by(cashierid scan store)
bysort cashierid (scan): gen prod_gain = itempm_tln - itempm_tln[_n - 1]
drop if mi(prod_gain)
sort cashierid
svmat B
rename B1 base
label var base "Conventional: Scanning speed"
label var prod_gain "Effect of scan-only"
sum base, de
outreg, clear(hetero)
reg prod_gain base, r
outreg, merge(hetero) $outopt addrows("Store f.e." "No") ///
	ctitle("Variables" "(a) Base")

areg prod_gain base, absorb(store) r
outreg, merge(hetero) $outopt addrows("Store f.e." "Yes") ///
	ctitle("Variables" "(b) With store f.e.")
	
areg prod_gain base if base < 0.7 & base > -0.4, absorb(store) r
outreg, merge(hetero) $outopt addrows("Store f.e." "Yes") ///
	ctitle("Variables" "(c) Excluding outliers")

outreg using "TableB4.doc", $outopt replay(hetero) replace	
restore

** Table B2. Cashier productivity: Robustness **

eststo clear

*column (d)
bysort cashierid: egen firstshift=min(shiftno)
areg itempm_tln scan worktime_tln i.day##i.hour if shiftno ~= firstshift, absorb(cashierid) cluster(cashierid) 
postreg scan worktime_tln 
eststo m4

*column (e)
gen cum_hr = (cumtran/worktime)*60
gen cum_hr_ln = log(cum_hr)

areg cum_hr_ln scan worktime_tln i.day##i.hour, absorb(cashierid) cluster(cashierid) 
postreg scan worktime_tln 
eststo m5

*columns (a)-(c)	
preserve
use cashier-wt0.dta, clear
areg itempm_tln scan worktime_tln i.day##i.hour if nottrim, absorb(cashierid) cluster(cashierid) 
postreg scan worktime_tln 
eststo m1

areg itempm_wln scan worktime_wln i.day##i.hour if everboth, absorb(cashierid) cluster(cashierid) 
postreg scan worktime_wln
eststo m2

areg itempm_tln scan worktime_tln i.day##i.hour if trim5 & everboth, absorb(cashierid) cluster(cashierid) 
postreg scan worktime_tln 
eststo m3

esttab m1 m2 m3 m4 m5 using "TableB2.rtf", ///
	cells(b(star fmt(3)) p(par)) star(* 0.10 ** 0.05 *** 0.01)	nocons style(fixed) ///
	stats(cashier N r2 lo hi, layout(@ @ @ `""[@, @]""') fmt(0 0 3)) label ///
	replace indicate("Day x Hour f.e. = *.day *.hour") ///
	mtitle("(a) All cashiers" "(b) Winsorized data" "(c) Exc top 5%" "(d) Exc first day in experiment" "(e) Customer service rate") collabels(none) title("Table B2. Cashier productivity: Robustness")

restore
	

** Table B3. Cluster by store-day

egen store_day = group(store day)

capture program drop postregg
program postregg, eclass
	boottest `1', cluster(store_day) nograph seed(12345)
	mat pboot = r(p) 
	mat ci = r(CI)
	estadd scalar lo = ci[1,1]
	estadd scalar hi = ci[1,2]
	
	forvalue i = 2(1)1000{
		if "``i''" == "" {
			continue, break
		}
		boottest ``i'', cluster(store_day) nograph seed(12345)
		mat pboot = [pboot , r(p)]
	}	
	mat colname pboot = `*' // _cons
	ereturn mat p = pboot
	
	unique cashierid if e(sample)
	estadd scalar cashier = r(unique), replace
end


eststo clear

reg itempm_tln scan worktime_tln, cluster(cashierid) 
postregg scan worktime_tln
eststo m6
  
reg itempm_tln scan worktime_tln store_1 store_2 store_3, cluster(cashierid) 
postregg scan worktime_tln store_1 store_2 store_3
eststo m7
  
areg itempm_tln scan worktime_tln, absorb(cashierid) cluster(cashierid)
postregg scan worktime_tln
eststo m8
    
areg itempm_tln scan worktime_tln i.date i.hour, absorb(cashierid) cluster(cashierid)
postregg scan worktime_tln
eststo m9

areg itempm_tln scan worktime_tln i.day##i.hour, absorb(cashierid) cluster(cashierid)
postregg scan worktime_tln
eststo m10

esttab m6 m7 m8 m9 m10 using "TableB3.rtf", ///
	cells(b(star fmt(3)) p(par)) star(* 0.10 ** 0.05 *** 0.01)	nocons style(fixed) star ///
	stats(cashier N r2 lo hi, layout(@ @ @ `""[@, @]""') fmt(0 0 3)) label ///
	replace indicate("Date f.e. = *.date" "Hour f.e. = *.hour" ///
	"Day x Hour f.e. = *.day") mtitle("(a) Scan-only" "(b) Store f.e." "(c)Cashier f.e." ///
	"(d) Cashier, date & hour f.e." "(e) Cashier & day*hour f.e.") collabels(none) ///
	title("Table B3. Cluster by store-day")

** Table B5: Balance Tests of Purchase Charicteristics**
eststo clear

local transvar basketsize basketval_tln itemvalue_tln paycash 
foreach var of local transvar {
areg `var' scan worktime_tln i.day##i.hour, absorb(cashierid) cluster(cashierid) 
postreg scan worktime_tln
eststo m_`var'
}
esttab m_basketsize m_basketval_tln m_itemvalue_tln m_paycash ///
	using "TableB5.rtf", ///
	cells(b(star fmt(3)) p(par)) star(* 0.10 ** 0.05 *** 0.01)	nocons style(fixed) ///
	stats(cashier N r2 lo hi, layout(@ @ @ `""[@, @]""') fmt(0 0 3)) label ///
	replace indicate("Day x Hour f.e. = *.day *.hour") mtitle("(a) Basket Size" "(b) Basket Value" ///
	"(c)Average Item Price" "(d) Pay by Cash") collabels(none) ///
	title("Table B5. Purchase characteristics: Balance tests")

/** Table B6 is skipped to protect sensitive information**/

	
** Table B7. Alternative Mechanisms: learning ** 

gen trad_scan = scan == 0 & scan_prevday == 1 if !mi(scan_prevday)
gen trad_trad = scan == 0 & trad_prevday == 1 if !mi(trad_prevday)

eststo clear
areg itempm_tln scan_scan scan_trad worktime_tln i.day##i.hour, absorb(cashierid) cluster(cashierid) 
postreg scan_scan scan_trad worktime_tln
boottest scan_scan == scan_trad, cluster(cashierid) nograph seed(12345)
eststo m1

ivreg2 itempm_tln scan (cumtran_tln_dm = cumtran_30_ln) ///
	worktime_tln timeonshift_tln i.day##i.hour i.cashierid, cluster(cashierid) ffirst
est store iv
areg cumtran_tln_dm scan cumtran_30_ln worktime_tln timeonshift_tln i.day##i.hour, absorb(cashierid) cluster(cashierid) 
postreg scan cumtran_30_ln worktime_tln timeonshift_tln
eststo m2
est restore iv
postreg scan cumtran_tln_dm worktime_tln timeonshift_tln 
eststo m3
    
ivreg2 itempm_tln scan ///
	(cumtran_tln_dm scan_cumtran_tln_dm = cumtran_30_ln scan_cumtran_30) ///
	worktime_tln timeonshift_tln i.day##i.hour i.cashierid,  cluster(cashierid) ffirst
postreg scan cumtran_tln_dm scan_cumtran_tln_dm worktime_tln timeonshift_tln  
eststo m4

gen scan_worktime_tln=scan*worktime_tln
label var scan_worktime_tln "Scan-only x counter work time (ln)"
areg itempm_tln scan scan_worktime_tln worktime_tln i.day##i.hour, absorb(cashierid) cluster(cashierid) 
postreg scan scan_worktime_tln worktime_tln
eststo m5

esttab m1 m2 m3 m4 m5 using "TableB7.rtf", ///
	cells(b(star fmt(3)) p(par)) star(* 0.10 ** 0.05 *** 0.01)	nocons style(fixed) ///
	stats(cashier N r2 rkf lo hi, layout(@ @ @ @ `""[@, @]""') fmt(0 0 3)) label ///
	replace indicate("Cashier f.e. = *.cashierid" ///
	"Day x Hour f.e. = *.day *.hour") ///
	mtitle("(a) Learning by day" "(b) Within a day: First stage" "(c) Within a day: IV" "(d) Within a day: IV" "(e) Counter hours") ///
	collabels(none) order($cntrvar) ///
	title("Table B7. Alternative mechanism: Learning") 
	


	
